package com.tjb.service.impl;

import cn.hutool.core.io.FileUtil;
import com.tjb.service.CsvService;
import com.tjb.service.TsFileService;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * @author tjb
 * @version 1.0
 * @date 2024/7/10 20:48
 */
@Service
public class CsvServiceImpl implements CsvService {
    @Resource
    private TsFileService tsFileService;
    /**
     * 解析csv成为一个对象
     * describe:`CSVParser parser = new CSVParser(new FileReader(csvFile), CSVFormat.DEFAULT)` 这段代码并没有一次性将整个文件内容读入内存。`CSVParser` 是基于流的方式来处理CSV文件的，这意味着它会逐行读取文件，而不是一次性加载整个文件。
     * 当你创建 `CSVParser` 实例时，它开始准备读取由 `FileReader` 提供的文件流。当你遍历 `CSVParser` 实例以获取 `CSVRecord` 对象时（如 `for (CSVRecord record : parser)` 循环），`CSVParser` 会按需读取文件的每一行，将其解析为 `CSVRecord` 对象。
     * 这种方式是内存效率较高的，因为它不需要将整个文件加载到内存中，而是逐行处理，这对于处理大型CSV文件尤其重要。每次迭代只处理当前行，并在处理完当前行后继续读取下一行，直到文件结束。
     * @param file : 上传的文件
     * @return : 返回的集合
     */
    @Override
    public List<T> parseCsvToT(File file) {
        //判断文件的合法性
        if (FileUtil.isEmpty(file)) {
            return Collections.emptyList();
        }
        //定义批次大小
        int batchSize = 1000;
        //解析文件,用默认的分割符号
        try (CSVParser parser = CSVParser.parse(new FileReader(file), CSVFormat.DEFAULT.withHeader())) {
            //防止在高并发情况下反复多次调用该循环，导致崩溃
            synchronized (CsvServiceImpl.class){
                //创建集合，用于保存批次数据
                List<CSVRecord> batchData = new ArrayList<>();
                //每次循环parse，就相当于读取一行csv文件
                for (CSVRecord record : parser) {
                    batchData.add(record);
                    //如果达到规定的数据量大小，就进行数据处理
                    if (batchData.size() == batchSize) {
                        CompletableFuture.runAsync(() -> {
                            processBatch(batchData, file);
                            batchData.clear();
                        }).thenRun(() -> {
                            // 这里可以执行不需要结果的后续操作
                        });
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return Collections.emptyList();
    }

    /**
     * 处理大批量数据
     * @param batchData : 待处理的数据
     */
    private void processBatch(List<CSVRecord> batchData, File file) {
        tsFileService.writeDataToTsFile(batchData, file);
    }

    @Override
    public List<String> parseCsvGetHeaders(File file) throws FileNotFoundException {
        List<String> headerList = new ArrayList<>();
        if (FileUtil.isEmpty(file)) {
            return headerList;
        }
        //读取文件的第一行，获取头部文件信息
        FileReader reader = new FileReader(file);
        try (CSVParser parser = CSVParser.parse(reader, CSVFormat.DEFAULT.withHeader())) {
            //解析的每一行记录
            headerList = parser.getHeaderNames();
            return headerList;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
